package com.fengniu.ejb.dao.impl;

import java.util.ArrayList;
import java.util.List;

import javax.ejb.Local;
import javax.ejb.Remote;
import javax.ejb.Stateless;
import javax.interceptor.Interceptors;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;

import org.apache.log4j.Logger;
import org.jboss.ejb3.annotation.LocalBinding;
import org.jboss.ejb3.annotation.RemoteBinding;

import com.fengniu.ejb.dao.CategoryDaoLocal;
import com.fengniu.ejb.dao.CategoryDaoRemote;
import com.fengniu.ejb.dao.interceptor.TracingInterceptor;
import com.fengniu.ejb.dao.util.DaoUtil;
import com.fengniu.ejb.dao.util.IEJBConstants;
import com.fengniu.ejb.entity.Category;
import com.fengniu.ejb.entity.Category2Category;
import com.fengniu.ejb.entity.User;

/**
 * @author conan
 * 
 */
@Stateless
@Local ({CategoryDaoLocal.class})
@LocalBinding(jndiBinding = IEJBConstants.CategoryDaoLocalJndiName)
@Remote ({CategoryDaoRemote.class})
@RemoteBinding(jndiBinding = IEJBConstants.CategoryDaoRemoteJndiName)
@Interceptors ({TracingInterceptor.class})
public class CategoryDaoImpl implements CategoryDaoLocal, CategoryDaoRemote {
	static Logger logger = Logger.getLogger(CategoryDaoImpl.class);

	/**
	 * 
	 */
	private static final long serialVersionUID = 5851122982667218379L;

	@PersistenceContext(unitName = "default")
	protected EntityManager em;

	public Category saveCategory(Category category) {
		return em.merge(category);
	}

	public List<Category> getListCategoryPrimaryTrailBy(String categoryId) {
		List<Category> result = null;

		Category category = findCategoryByCategoryId(categoryId);
		if (category != null) {
			result = getListCategoryPrimaryTrailBy(category.getSysId());
		}
		return result;
	}

	public List<Category> getListCategoryPrimaryTrailBy(long categorySysId) {

		List<Category> result = new ArrayList<Category>(0);
		Category pg = em.find(Category.class, categorySysId);
		if (pg != null && pg.getPrimaryParent() != null) {
			result = getListCategoryPrimaryTrailBy(pg.getPrimaryParent().getSysId());
		}
		if (pg != null)
			result.add(pg);
		return result;
	}

	public List<Category> getListChildCategoryBy(String parentCategoryId, int pgno, int pgsize, String orderBy) {
		// TODO seems use treecache, it will be slowdown?????
		List<Category> categorys = null;
		if (parentCategoryId != null) {
			Query q = em.createNamedQuery("CategoryDao.eql.getListChildCategoryBy").setParameter("parentCategoryId",
					parentCategoryId).setHint("org.hibernate.cacheable", new Boolean(true));
			//.setHint(			"org.hibernate.cacheRegion", "/entity/Category/ChildCategory")
			
			categorys = q.setFirstResult(pgno * pgsize).setMaxResults(pgsize).getResultList();
		}
		return categorys;
	}

	public Category findCategoryByCategoryId(String categoryId) {
		Query q = em.createNamedQuery("CategoryDao.eql.getListCategoryByCategoryId").setParameter("categoryId",
				categoryId).setMaxResults(1).setHint("org.hibernate.cacheable", new Boolean(true));
		//.setHint(		"org.hibernate.cacheRegion", "/entity/Category/Single")
		List<Category> categorys = q.getResultList();
		Category result = null;
		if (categorys != null && categorys.size() > 0) {
			result = categorys.get(0);
		}
		return result;
	}

	public void setEm(EntityManager em) {
		this.em = em;
	}

	public Category findCategoryBySysId(long categorySysId) {
		return em.find(Category.class, categorySysId);
	}

	private Query getQueryCategory2CategoryBy(String categoryId, Integer[] relationIds, String categoryId2,
			Integer[] statusIds, String orderBy, boolean isGetList) {
		String ent = isGetList ? "g2g" : "count(g2g)";

		String eql = "select " + ent + " from  Category2Category g2g";
		String whereand = "";
		if (categoryId != null) {
			whereand = DaoUtil.getWhereOrAndStr(whereand);
			eql += whereand + "  g2g.category.categoryId=:categoryId ";
		}
		if (DaoUtil.isNull(relationIds) == false) {
			whereand = DaoUtil.getWhereOrAndStr(whereand);
			eql += whereand + "  g2g.relationId IN (:relationIds) ";
		}
		if (categoryId2 != null) {
			whereand = DaoUtil.getWhereOrAndStr(whereand);
			eql += whereand + "  g2g.category2.categoryId=:categoryId2 ";
		}
		if (DaoUtil.isNull(statusIds) == false) {
			whereand = DaoUtil.getWhereOrAndStr(whereand);
			eql += whereand + "  g2g.status IN (:statusIds) ";
		}
		logger.info("eql=[" + eql + "]");

		Query q = em.createQuery(eql);
		if (categoryId != null) {
			q.setParameter("categoryId", categoryId);
		}
		if (DaoUtil.isNull(relationIds) == false) {
			List rts = DaoUtil.getListFromArray(relationIds);
			q.setParameter("relationIds", rts);
		}
		if (categoryId2 != null) {
			q.setParameter("categoryId2", categoryId2);
		}
		if (DaoUtil.isNull(statusIds) == false) {
			q.setParameter("statusIds", statusIds);
		}
		return q;
	}

	public Category2Category saveCategory2Category(Category2Category g22g) {
		return em.merge(g22g);

	}

	public List<Category> getListAllCategory() {
		List<Category> result = null;
		Query q = em.createQuery("select p from Category p ");
		result = q.getResultList();
		return result;
	}

	public void deleteCategoryByCategoryId(String categoryId) {
		Category u = findCategoryByCategoryId(categoryId);
		if (u != null)
			em.remove(u);
	}

	// -----------------------------------------------------
	@SuppressWarnings("unchecked")
	private List<User> findByCategoryProperty(String propertyName, Object value, int size) {
		String eql = "SELECT g FROM Category g where g." + propertyName + "= :propertyValue";
		logger.info("eql=[" + eql + "] propertyValue=" + value);

		return em.createQuery(eql).setParameter("propertyValue", value).setFirstResult(0).setMaxResults(size)
				.getResultList();
	}

	public long getCountCategory2CategoryBy(String categoryId, Integer[] relationIds, String categoryId2,
			Integer[] statusIds) {
		Long result = new Long(0);
		Query q = this.getQueryCategory2CategoryBy(categoryId, relationIds, categoryId2, statusIds, null, false)
				.setHint("org.hibernate.cacheable", new Boolean(true));
		//.setHint("org.hibernate.cacheRegion",		"/entity/Category/RelatedCategory/Count")

		result = (Long) q.getSingleResult();

		return result;
	}

	public List<Category2Category> getListCategory2CategoryBy(String categoryId, Integer[] relationIds,
			String categoryId2, Integer[] statusIds, String orderBy, int pgno, int pgsize) {
		Query q = this.getQueryCategory2CategoryBy(categoryId, relationIds, categoryId2, statusIds, null, true)
				.setHint("org.hibernate.cacheable", new Boolean(true));
		//.setHint("org.hibernate.cacheRegion",	"/entity/Category/RelatedCategory/List")
		List result = DaoUtil.getResultList(q, pgno, pgsize);
		return result;
	}

}
